const fs = require('fs-extra');
const path = require('path');
const { format } = require('date-fns');
const winston = require('winston');
require('winston-daily-rotate-file');
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');
dayjs.extend(utc);
dayjs.extend(timezone);
const CHINA_TZ = 'Asia/Shanghai';

/**
 * 日志级别定义
 */
const LOG_LEVELS = {
  ERROR: 'error',
  WARN: 'warning',
  INFO: 'info',
  DEBUG: 'debug',
  SUCCESS: 'success'
};

// 日志存储目录
const LOGS_DIR = path.join(__dirname, '..', 'logs');

// 确保日志目录存在
if (!fs.existsSync(LOGS_DIR)) {
  fs.mkdirSync(LOGS_DIR, { recursive: true });
}

// 创建Winston日志格式
const logFormat = winston.format.combine(
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
  winston.format.json()
);

// 创建Winston日志传输器
const fileTransport = new winston.transports.DailyRotateFile({
  dirname: LOGS_DIR,
  filename: '%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  maxSize: '20m',
  maxFiles: '14d',
  format: logFormat
});

// 创建Winston日志记录器
const winstonLogger = winston.createLogger({
  level: 'info',
  format: logFormat,
  transports: [
    fileTransport,
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        winston.format.printf(({ timestamp, level, message, namespace, ...rest }) => {
          // 确保message是字符串，如果是对象则转换为字符串
          const formattedMessage = typeof message === 'object' 
            ? JSON.stringify(message) 
            : String(message);
          
          const meta = Object.keys(rest).length ? ` ${JSON.stringify(rest)}` : '';
          return `${timestamp} [${namespace || 'system'}] ${level}: ${formattedMessage}${meta}`;
        })
      )
    })
  ]
});

/**
 * 创建日志记录器
 * @param {string} namespace 日志命名空间
 * @returns {Object} 日志记录器对象
 */
function createLogger(namespace) {
  // 确保消息是字符串
  const ensureString = (message) => {
    if (typeof message === 'object') {
      return JSON.stringify(message);
    }
    return String(message);
  };
  
  return {
    /**
     * 错误日志
     * @param {string} message 日志消息
     * @param {Object} meta 元数据
     */
    error: (message, meta = {}) => {
      winstonLogger.error(ensureString(message), { namespace, ...meta });
    },
    
    /**
     * 警告日志
     * @param {string} message 日志消息
     * @param {Object} meta 元数据
     */
    warn: (message, meta = {}) => {
      winstonLogger.warn(ensureString(message), { namespace, ...meta });
    },
    
    /**
     * 信息日志
     * @param {string} message 日志消息
     * @param {Object} meta 元数据
     */
    info: (message, meta = {}) => {
      winstonLogger.info(ensureString(message), { namespace, ...meta });
    },
    
    /**
     * 调试日志
     * @param {string} message 日志消息
     * @param {Object} meta 元数据
     */
    debug: (message, meta = {}) => {
      winstonLogger.debug(ensureString(message), { namespace, ...meta });
    },
    
    /**
     * 成功日志
     * @param {string} message 日志消息
     * @param {Object} meta 元数据
     */
    success: (message, meta = {}) => {
      winstonLogger.info(ensureString(message), { namespace, level: LOG_LEVELS.SUCCESS, ...meta });
    }
  };
}

/**
 * 日志时间格式化函数
 */
function formatChinaTime(ts) {
  return dayjs(ts).tz(CHINA_TZ).format('YYYY-MM-DD HH:mm:ss');
}

/**
 * 日志服务
 */
const logService = {
  /**
   * 获取日志
   * @param {Object} options 选项
   * @param {string} options.app 应用名称
   * @param {string} options.type 日志类型
   * @param {number} options.limit 限制数量
   * @param {string} options.category 日志类别（构建/部署）
   * @returns {Array} 日志列表
   */
  getLogs: ({ app, type, limit = 100, category } = {}) => {
    const logs = [];
    
    if (!fs.existsSync(LOGS_DIR)) {
      return logs;
    }
    
    // 获取所有日志文件并按日期排序（最新的在前面）
    const logFiles = fs.readdirSync(LOGS_DIR)
      .filter(file => file.endsWith('.log'))
      .sort()
      .reverse();
    
    for (const file of logFiles) {
      if (logs.length >= limit) break;
      
      const filePath = path.join(LOGS_DIR, file);
      let content;
      
      try {
        content = fs.readFileSync(filePath, 'utf8');
      } catch (error) {
        console.error(`读取日志文件失败: ${filePath}`, error);
        continue;
      }
      
      const lines = content.split('\n').filter(Boolean);
      
      for (const line of lines) {
        if (logs.length >= limit) break;
        
        try {
          const log = JSON.parse(line);
          
          // 过滤特定应用的日志
          if (app && (!log.message || !log.message.includes(app))) {
            continue;
          }
          
          // 过滤特定类型的日志
          if (type && log.level !== type) {
            continue;
          }
          
          // 过滤特定类别的日志
          if (category === 'build' && (!log.message || !log.message.includes('构建'))) {
            continue;
          }
          
          if (category === 'deploy' && (!log.message || !log.message.includes('部署'))) {
            continue;
          }
          
          // 提取应用名
          let appName = '系统';
          if (log.message && log.message.includes('[')) {
            const match = log.message.match(/\[(.*?)\]/);
            if (match && match[1]) {
              appName = match[1];
            }
          }
          
          // 格式化日志消息
          let message = log.message || '';
          if (message.includes('[')) {
            message = message.replace(/\[.*?\]/, '').trim();
          }
          
          logs.push({
            time: log.timestamp ? formatChinaTime(log.timestamp) : formatChinaTime(Date.now()),
            app: appName,
            level: log.level || 'info',
            message: message
          });
        } catch (error) {
          console.error(`解析日志行失败: ${line}`, error);
        }
      }
    }
    
    return logs.slice(0, limit);
  },
  
  /**
   * 清除日志
   * @param {Object} options 选项
   * @param {string} options.app 应用名称
   * @param {string} options.category 日志类别（构建/部署）
   * @returns {boolean} 是否成功
   */
  clearLogs: ({ app, category } = {}) => {
    try {
      if (!fs.existsSync(LOGS_DIR)) {
        return true;
      }
      
      const logFiles = fs.readdirSync(LOGS_DIR).filter(file => file.endsWith('.log'));
      
      for (const file of logFiles) {
        const filePath = path.join(LOGS_DIR, file);
        
        if (!app && !category) {
          // 如果没有指定应用和类别，清空文件
          fs.writeFileSync(filePath, '');
          continue;
        }
        
        // 读取文件内容
        let content;
        try {
          content = fs.readFileSync(filePath, 'utf8');
        } catch (error) {
          console.error(`读取日志文件失败: ${filePath}`, error);
          continue;
        }
        
        const lines = content.split('\n').filter(Boolean);
        
        // 过滤日志行
        const filteredLines = lines.filter(line => {
          try {
            const log = JSON.parse(line);
            
            // 如果指定了应用，过滤包含该应用的日志
            if (app && log.message && log.message.includes(app)) {
              return false;
            }
            
            // 如果指定了类别，过滤该类别的日志
            if (category === 'build' && log.message && log.message.includes('构建')) {
              return false;
            }
            
            if (category === 'deploy' && log.message && log.message.includes('部署')) {
              return false;
            }
            
            return true;
          } catch (error) {
            return true; // 保留无法解析的行
          }
        });
        
        // 重写文件
        fs.writeFileSync(filePath, filteredLines.join('\n') + (filteredLines.length > 0 ? '\n' : ''));
      }
      
      return true;
    } catch (error) {
      console.error('清除日志失败:', error);
      return false;
    }
  }
};

module.exports = {
  createLogger,
  LOG_LEVELS,
  logService
}; 